package com.means.polymerize.assembly.aspect.logs;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.means.polymerize.common.constants.ResultCode;
import com.means.polymerize.common.lang.DataResult;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicReference;

/**
 * The type Global aspect.
 *
 * @author xuhaifneg
 * @date 2021.03.31
 */
@Slf4j
@Aspect
@Component
public class GlobalAspect {
    /**
     * 定义AOP签名 --> 项目代码(所有class名成带有Controller字符的)
     */
    @Pointcut("execution(* com.means.polymerize.mainstay..*Controller*.*(..))")
    public void webLogProject() {
    }

    /**
     * 环绕通知,环绕增强，相当于MethodInterceptor
     *
     * @param pjp the pjp
     * @return the object
     */
    @SneakyThrows
    @Around(value = "webLogProject()")
    public Object webLogProjectSurround(final ProceedingJoinPoint pjp) {
        LogsDomain.startRequest();
        final AtomicReference<DataResult<?>> output = new AtomicReference<>();
        try {
            final Object proceed = pjp.proceed();
            if (proceed instanceof DataResult) {
                output.set((DataResult<?>) proceed);
            } else {
                output.set(DataResult.success(proceed));
            }
            return proceed;
        } catch (Exception e) {
            // 其他异常，将堆栈异常存储至数据库中，并抛出运行时异常
            e.printStackTrace();
            ThreadUtil.execAsync(() -> LogsDomain.endRequest(DataResult.custom(ResultCode.INTERNAL_ERROR.code, ExceptionUtil.getRootCauseMessage(e), ExceptionUtil.stacktraceToString(e))), true).run();
            throw e;
        } finally {
            ThreadUtil.execAsync(() -> LogsDomain.endRequest(output.get()), true).run();
        }
    }

}
